<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Example: Adding and Removing Tabs</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.4.0pr3/build/cssgrids/grids-min.css">
    <link rel="stylesheet" href="../assets/css/main.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <script src="../../build/yui/yui-min.js"></script>
</head>
<body>

<div id="doc">
    <h1>Example: Adding and Removing Tabs</h1>

    

    <div class="yui3-g">
        <div id="main" class="yui3-u">
            <div class="content"><style scoped>
.yui3-tabview {
    margin-bottom: 1em;
}

.yui3-skin-sam .yui3-tab {
    position: relative;
}

.yui3-skin-sam .yui3-tabview-removeable .yui3-tab-label,
.yui3-skin-sam .yui3-tabview-removeable .yui3-tab-selected .yui3-tab-label {
    padding-right: 1.3em; /* make room for close link */
}

.yui3-skin-sam .yui3-tabview-removeable .yui3-tab-add {
    padding-right: 0.75em; /* no close link for add tab link */
}

.yui3-skin-sam .yui3-tab-add {
    color: #999;
    font: bold 120%/1 verdana;
    margin-left: 0.25em;
}

.yui3-tab-remove {
    color: #999;
    font:bold 80% verdana;
    position: absolute;
    right: 0.4em;
    top: 0.4em;
}

.yui3-tab-remove:hover {
    color: #666;
}

.yui3-skin-sam .yui3-tab-selected .yui3-tab-remove {
    top: 0.52em;
}

.yui3-skin-sam .yui3-tab-selected .yui3-tab-remove:hover {
    color: #fff;
}

#main #example-canvas .yui3-tabview .yui3-tab-selected a {
	color:white;
}

</style>
<div class="intro">
    <p>This example shows how to give <code>TabView</code> buttons for adding and removing tabs.</p>
</div>

<div class="example yui3-skin-sam">
<div id="demo">
    <ul>
        <li><a href="#foo">foo</a></li>
        <li><a href="#bar">bar</a></li>
        <li><a href="#baz">baz</a></li>
    </ul>
    <div>
        <div id="foo">
            <p>foo content</p>
        </div>
        <div id="bar">
            <p>bar content</p>
        </div>
        <div id="baz">
            <p>baz content</p>
        </div>
    </div>
</div>

<div id="demo2">
</div>

<div id="demo3">
</div>

<script type="text/javascript">
YUI().use('tabview', 'escape', 'plugin', function(Y) {
    var Addable = function(config) {
        Addable.superclass.constructor.apply(this, arguments);
    };

    Addable.NAME = 'addableTabs';
    Addable.NS = 'addable';

    Y.extend(Addable, Y.Plugin.Base, {
        ADD_TEMPLATE: '<li class="yui3-tab" title="add a tab">' +
                    '<a class="yui3-tab-label yui3-tab-add">+</a></li>',

        initializer: function(config) {
            var tabview = this.get('host');
            tabview.after('render', this.afterRender, this);
            tabview.get('contentBox')
                .delegate('click', this.onAddClick, '.yui3-tab-add', this);
        },

        getTabInput: function() {
            var tabview = this.get('host');
            return {
                label: Y.Escape.html(window.prompt('label:', 'new tab')),
                content: '<p>' + Y.Escape.html(window.prompt('content:', 'new content')) + '</p>',
                index: Number(window.prompt('index:', tabview.size()))
            }
        },

        afterRender: function(e) {
            var tabview = this.get('host');
            tabview.get('contentBox').one('> ul').append(this.ADD_TEMPLATE);
        },

        onAddClick: function(e) {
            e.stopPropagation();
            var tabview = this.get('host'),
                input = this.getTabInput();
            tabview.add(input, input.index);
        }
    });

    var Removeable = function(config) {
        Removeable.superclass.constructor.apply(this, arguments);
    };

    Removeable.NAME = 'removeableTabs';
    Removeable.NS = 'removeable';

    Y.extend(Removeable, Y.Plugin.Base, {
        REMOVE_TEMPLATE: '<a class="yui3-tab-remove" title="remove tab">x</a>',

        initializer: function(config) {
            var tabview = this.get('host'),
                cb = tabview.get('contentBox');

            cb.addClass('yui3-tabview-removeable');
            cb.delegate('click', this.onRemoveClick, '.yui3-tab-remove', this);

            // Tab events bubble to TabView
            tabview.after('tab:render', this.afterTabRender, this);
        },

        afterTabRender: function(e) {
            // boundingBox is the Tab's LI
            e.target.get('boundingBox').append(this.REMOVE_TEMPLATE);
        },

        onRemoveClick: function(e) {
            e.stopPropagation();
            var tab = Y.Widget.getByNode(e.target);
            tab.remove();
        }
    });

    var tabview = new Y.TabView({
        srcNode: '#demo',
        plugins: [Addable]
    });

    var tabview2 = new Y.TabView({
        children: [{
            label: 'foo',
            content: '<p>foo content</p>'
        }, {
            label: 'bar',
            content: '<p>bar content</p>'
        }, {
            label: 'baz',
            content: '<p>baz content</p>'
        }],
        plugins: [Removeable]
    });

    var tabview3 = new Y.TabView({
        children: [{
            label: 'foo',
            content: '<p>foo content</p>'
        }, {
            label: 'bar',
            content: '<p>bar content</p>'
        }, {
            label: 'baz',
            content: '<p>bar content</p>'
        }],
        plugins: [Addable, Removeable]
    });

    tabview.render();
    tabview2.render('#demo2');
    tabview3.render('#demo3');
});
</script>

</div>

<h2>Plugin Template</h2>

<p>In order to make these addons reusable, we can build them as plugins.  This
allows the option for multiple tabviews that mix and match functionality.
To get started, we will first fill in a basic <code>Plugin</code> template.
The <code>NAME</code> property is required to prefix events, classNames, et cetera.
The <code>NS</code> is the namespace where the plugin will live on the
<code>host</code>.  This is where its API can be accessed (e.g. "node.addable.destroy()").
Adding the <code>this._host</code> alias provides a convenient way to get back to the TabView
instance. Calling the superclass constructor kicks off the <code>Base</code> lifecycle,
which will call the <code>initializer</code>.

</p>

<pre class="code prettyprint">var Addable = function(config) {
    this._host = config.host;
    Addable.superclass.constructor.apply(this, arguments);
};

Addable.NAME = &#x27;addableTabs&#x27;;
Addable.NS = &#x27;addable&#x27;;

Y.extend(Addable, Y.Plugin.Base, {
    initializer: function(config) {
    }
});</pre>


<h2>Addable Tab Plugin</h2>

<p>To simplify adding new tabs, we are going to add a button that
users can click and that will prompt them for some details regarding the new tab.
The main task we are trying to accomplish is to add some HTML to the
<code>TabView</code>, listen for clicks on the button, prompt the user for input,
and update the tabs accordingly.</p>

<h3>HTML Template</h3>
<p>The first thing we need is a template for the markup to be generated.  Adding
this to the prototype allows separate customization for each <code>TabView</code>
instance. For this example, we want it to look and feel like another <code>Tab</code>
without actually being one.</p> 

<pre class="code prettyprint">Y.extend(Addable, Y.Plugin.Base, {
    ADD_TEMPLATE: &#x27;&lt;li class=&quot;yui3-tab&quot; title=&quot;add a tab&quot;&gt;&#x27; +
                &#x27;&lt;a class=&quot;yui3-tab-label yui3-tab-add&quot;&gt;+&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;&#x27;,

    initializer: function(config) {
    }
});</pre>


<h3>Adding the HTML</h3>
<p>Now that we have a markup template, we will need to add it to the <code>TabView</code>
somehow.  The <code>render</code> phase is the appropriate moment to do so.  Listening
for the <code>render</code> event will give us access to that moment.  Listening
for <code>after('render')</code> ensure that the rendering has actually happened. Then
we just need to find the tab list and, using the template, add the new item.
The <code>contentBox</code> provides a <code>Node</code> that can be used to manage
the <code>TabView</code> HTML.</p> 

<pre class="code prettyprint">Y.extend(Addable, Y.Plugin.Base, {
    ADD_TEMPLATE: &#x27;&lt;li class=&quot;yui3-tab&quot; title=&quot;add a tab&quot;&gt;&#x27; +
                &#x27;&lt;a class=&quot;yui3-tab-label yui3-tab-add&quot;&gt;+&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;&#x27;,

    initializer: function(config) {
        var tabview = this.get(&#x27;host&#x27;);
        tabview.after(&#x27;render&#x27;, this.afterRender, this);
    },

    afterRender: function(e) {
        var tabview = this.get(&#x27;host&#x27;);
        tabview.get(&#x27;contentBox&#x27;).one(&#x27;&gt; ul&#x27;).append(this.ADD_TEMPLATE);
    }
});</pre>


<h3>Handling the Click</h3>
<p>All that remains is to listen for clicks on the add button and prompt
the user for the relevant <code>Tab</code> data.  Again we can leverage
the <code>Node</code> API, this time to delegate clicks on the add button.
Stopping event propagation in our handler ensures that the event does
not bubble any further, preventing the <code>TabView</code> from trying
to handle it. To keep the example simple, a basic <code>prompt</code> is
used to get the user input.  This could be refined to use an
<code>Overlay</code> or other custom control.  The data is then handed off
to <code>TabView</code>'s <code>add</code> method.</p> 

<pre class="code prettyprint">Y.extend(Addable, Y.Plugin.Base, {
    ADD_TEMPLATE: &#x27;&lt;li class=&quot;yui3-tab&quot; title=&quot;add a tab&quot;&gt;&#x27; +
                &#x27;&lt;a class=&quot;yui3-tab-label yui3-tab-add&quot;&gt;+&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;&#x27;,

    initializer: function(config) {
        var tabview = this.get(&#x27;host&#x27;);
        tabview.after(&#x27;render&#x27;, this.afterRender, this);

        tabview.get(&#x27;contentBox&#x27;)
            .delegate(&#x27;click&#x27;, this.onAddClick, &#x27;.yui3-tab-add&#x27;, this);
    },

    afterRender: function(e) {
        this.get(&#x27;host&#x27;).get(&#x27;contentBox&#x27;).one(&#x27;&gt; ul&#x27;).append(this.ADD_TEMPLATE);
    },

    getTabInput: function() {
        return {
            label: window.prompt(&#x27;label:&#x27;, &#x27;new tab&#x27;),
            content: window.prompt(&#x27;content:&#x27;, &#x27;&lt;p&gt;new content&lt;&#x2F;p&gt;&#x27;),
            index: Number(window.prompt(&#x27;index:&#x27;, this._host.size()))
        }
    },

    onAddClick: function(e) {
        e.stopPropagation();
        var tabview = this.get(&#x27;host&#x27;);
            input = this.getTabInput();
        tabview.add(input, input.index);
    }
});</pre>


<h3>Using the Plugin</h3>
<p>Now we can go ahead and plug in our functionality.  This can be during
construction with the <code>plugins</code> attribute, or subsequently
via the <code>plug</code> method.</p> 

<pre class="code prettyprint">var tabview = new Y.TabView({
    children: [{
        label: &#x27;foo&#x27;,
        content: &#x27;&lt;p&gt;foo content&lt;&#x2F;p&gt;&#x27;
    }, {
        label: &#x27;bar&#x27;,
        content: &#x27;&lt;p&gt;bar content&lt;&#x2F;p&gt;&#x27;
    }, {
        label: &#x27;baz&#x27;,
        content: &#x27;&lt;p&gt;baz content&lt;&#x2F;p&gt;&#x27;
    }],
    plugins: [Addable]
});

&#x2F;&#x2F; or
&#x2F;&#x2F; tabview.plug(Addable);</pre>


<h2>Removeable Tabs Plugin</h2>
<p>The process for creating a removeable plugin for <code>TabView</code>
is very similar.  The full source is provided below.</p>

<pre class="code prettyprint">var Removeable = function(config) {
    Removeable.superclass.constructor.apply(this, arguments);
};

Removeable.NAME = &#x27;removeableTabs&#x27;;
Removeable.NS = &#x27;removeable&#x27;;

Y.extend(Removeable, Y.Plugin.Base, {
    REMOVE_TEMPLATE: &#x27;&lt;a class=&quot;yui3-tab-remove&quot; title=&quot;remove tab&quot;&gt;x&lt;&#x2F;a&gt;&#x27;,

    initializer: function(config) {
        var tabview = this.get(&#x27;host&#x27;),
            cb = tabview.get(&#x27;contentBox&#x27;);

        cb.addClass(&#x27;yui3-tabview-removeable&#x27;);
        cb.delegate(&#x27;click&#x27;, this.onRemoveClick, &#x27;.yui3-tab-remove&#x27;, this);

        &#x2F;&#x2F; Tab events bubble to TabView
        tabview.after(&#x27;tab:render&#x27;, this.afterTabRender, this);
    },

    afterTabRender: function(e) {
        &#x2F;&#x2F; boundingBox is the Tab&#x27;s LI
        e.target.get(&#x27;boundingBox&#x27;).append(this.REMOVE_TEMPLATE);
    },

    onRemoveClick: function(e) {
        e.stopPropagation();
        var tab = Y.Widget.getByNode(e.target);
        tab.remove();
    }
});</pre>

<h2>Complete Example Source</h2>
<pre class="code prettyprint">&lt;div id=&quot;demo&quot;&gt;
    &lt;ul&gt;
        &lt;li&gt;&lt;a href=&quot;#foo&quot;&gt;foo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
        &lt;li&gt;&lt;a href=&quot;#bar&quot;&gt;bar&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
        &lt;li&gt;&lt;a href=&quot;#baz&quot;&gt;baz&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
    &lt;div&gt;
        &lt;div id=&quot;foo&quot;&gt;
            &lt;p&gt;foo content&lt;&#x2F;p&gt;
        &lt;&#x2F;div&gt;
        &lt;div id=&quot;bar&quot;&gt;
            &lt;p&gt;bar content&lt;&#x2F;p&gt;
        &lt;&#x2F;div&gt;
        &lt;div id=&quot;baz&quot;&gt;
            &lt;p&gt;baz content&lt;&#x2F;p&gt;
        &lt;&#x2F;div&gt;
    &lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;div id=&quot;demo2&quot;&gt;
&lt;&#x2F;div&gt;

&lt;div id=&quot;demo3&quot;&gt;
&lt;&#x2F;div&gt;

&lt;script type=&quot;text&#x2F;javascript&quot;&gt;
YUI().use(&#x27;tabview&#x27;, &#x27;escape&#x27;, &#x27;plugin&#x27;, function(Y) {
    var Addable = function(config) {
        Addable.superclass.constructor.apply(this, arguments);
    };

    Addable.NAME = &#x27;addableTabs&#x27;;
    Addable.NS = &#x27;addable&#x27;;

    Y.extend(Addable, Y.Plugin.Base, {
        ADD_TEMPLATE: &#x27;&lt;li class=&quot;yui3-tab&quot; title=&quot;add a tab&quot;&gt;&#x27; +
                    &#x27;&lt;a class=&quot;yui3-tab-label yui3-tab-add&quot;&gt;+&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;&#x27;,

        initializer: function(config) {
            var tabview = this.get(&#x27;host&#x27;);
            tabview.after(&#x27;render&#x27;, this.afterRender, this);
            tabview.get(&#x27;contentBox&#x27;)
                .delegate(&#x27;click&#x27;, this.onAddClick, &#x27;.yui3-tab-add&#x27;, this);
        },

        getTabInput: function() {
            var tabview = this.get(&#x27;host&#x27;);
            return {
                label: Y.Escape.html(window.prompt(&#x27;label:&#x27;, &#x27;new tab&#x27;)),
                content: &#x27;&lt;p&gt;&#x27; + Y.Escape.html(window.prompt(&#x27;content:&#x27;, &#x27;new content&#x27;)) + &#x27;&lt;&#x2F;p&gt;&#x27;,
                index: Number(window.prompt(&#x27;index:&#x27;, tabview.size()))
            }
        },

        afterRender: function(e) {
            var tabview = this.get(&#x27;host&#x27;);
            tabview.get(&#x27;contentBox&#x27;).one(&#x27;&gt; ul&#x27;).append(this.ADD_TEMPLATE);
        },

        onAddClick: function(e) {
            e.stopPropagation();
            var tabview = this.get(&#x27;host&#x27;),
                input = this.getTabInput();
            tabview.add(input, input.index);
        }
    });

    var Removeable = function(config) {
        Removeable.superclass.constructor.apply(this, arguments);
    };

    Removeable.NAME = &#x27;removeableTabs&#x27;;
    Removeable.NS = &#x27;removeable&#x27;;

    Y.extend(Removeable, Y.Plugin.Base, {
        REMOVE_TEMPLATE: &#x27;&lt;a class=&quot;yui3-tab-remove&quot; title=&quot;remove tab&quot;&gt;x&lt;&#x2F;a&gt;&#x27;,

        initializer: function(config) {
            var tabview = this.get(&#x27;host&#x27;),
                cb = tabview.get(&#x27;contentBox&#x27;);

            cb.addClass(&#x27;yui3-tabview-removeable&#x27;);
            cb.delegate(&#x27;click&#x27;, this.onRemoveClick, &#x27;.yui3-tab-remove&#x27;, this);

            &#x2F;&#x2F; Tab events bubble to TabView
            tabview.after(&#x27;tab:render&#x27;, this.afterTabRender, this);
        },

        afterTabRender: function(e) {
            &#x2F;&#x2F; boundingBox is the Tab&#x27;s LI
            e.target.get(&#x27;boundingBox&#x27;).append(this.REMOVE_TEMPLATE);
        },

        onRemoveClick: function(e) {
            e.stopPropagation();
            var tab = Y.Widget.getByNode(e.target);
            tab.remove();
        }
    });

    var tabview = new Y.TabView({
        srcNode: &#x27;#demo&#x27;,
        plugins: [Addable]
    });

    var tabview2 = new Y.TabView({
        children: [{
            label: &#x27;foo&#x27;,
            content: &#x27;&lt;p&gt;foo content&lt;&#x2F;p&gt;&#x27;
        }, {
            label: &#x27;bar&#x27;,
            content: &#x27;&lt;p&gt;bar content&lt;&#x2F;p&gt;&#x27;
        }, {
            label: &#x27;baz&#x27;,
            content: &#x27;&lt;p&gt;baz content&lt;&#x2F;p&gt;&#x27;
        }],
        plugins: [Removeable]
    });

    var tabview3 = new Y.TabView({
        children: [{
            label: &#x27;foo&#x27;,
            content: &#x27;&lt;p&gt;foo content&lt;&#x2F;p&gt;&#x27;
        }, {
            label: &#x27;bar&#x27;,
            content: &#x27;&lt;p&gt;bar content&lt;&#x2F;p&gt;&#x27;
        }, {
            label: &#x27;baz&#x27;,
            content: &#x27;&lt;p&gt;bar content&lt;&#x2F;p&gt;&#x27;
        }],
        plugins: [Addable, Removeable]
    });

    tabview.render();
    tabview2.render(&#x27;#demo2&#x27;);
    tabview3.render(&#x27;#demo3&#x27;);
});
&lt;&#x2F;script&gt;</pre>

</div>
        </div>

        <div id="sidebar" class="yui3-u">
            

            
                <div class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Examples</h2>
                    </div>

                    <div class="bd">
                        <ul class="examples">
                            
                                
                                    <li data-description="This example shows how to create a TabView wigdet from existing HTML.">
                                        <a href="tabview-basic.html">TabView from Existing Markup</a>
                                    </li>
                                
                            
                                
                                    <li data-description="This example shows how to create a TabView wigdet from JavaScript.">
                                        <a href="tabview-fromjs.html">Dynamic TabView from JavaScript</a>
                                    </li>
                                
                            
                                
                                    <li data-description="This example shows how to add and remove Tabs.">
                                        <a href="tabview-add-remove.html">Adding and Removing Tabs</a>
                                    </li>
                                
                            
                                
                                    <li data-description="This example shows how to load tab content remotely using a YQL plugin.">
                                        <a href="tabview-yql.html">Loading Tab Content</a>
                                    </li>
                                
                            
                                
                            
                        </ul>
                    </div>
                </div>
            

            
                <div class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Examples That Use This Component</h2>
                    </div>

                    <div class="bd">
                        <ul class="examples">
                            
                                
                            
                                
                            
                                
                            
                                
                            
                                
                                    <li data-description="Demonstrates how to add browser history support to a TabView widget using the History Utility.">
                                        <a href="../history/history-tabview.html">History + TabView</a>
                                    </li>
                                
                            
                        </ul>
                    </div>
                </div>
            
        </div>
    </div>
</div>

<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>

</body>
</html>
